﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.Request
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Security.Principal;

namespace Microsoft.InfoCards
{
  internal abstract class Request : IDisposable
  {
    private static Request.RequestHandleDictionary s_existingClientRequests = new Request.RequestHandleDictionary();
    private static ExceptionTranslationTable s_exceptionToHResultTable = ExceptionTranslationTable.Instance;
    private static object s_syncRoot = new object();
    private int m_lcid = -1;
    private Stream m_inArgs;
    private Stream m_outArgs;
    private int m_requestHandle;
    private IWebProxy m_proxy;
    private object m_syncRoot;
    private IntPtr m_rpcHandle;
    private Exception m_processingException;
    private ExceptionList m_recoverableExceptions;
    private WindowsImpersonationContext m_impersonationContext;
    private int m_initHResult;
    private string m_extendedErrorMessage;

    protected Request(
      IntPtr rpcHandle,
      Stream inArgs,
      Stream outArgs,
      ExceptionList recoverableExceptions)
    {
      this.m_inArgs = inArgs;
      this.m_outArgs = outArgs;
      this.m_rpcHandle = rpcHandle;
      this.m_recoverableExceptions = recoverableExceptions;
      this.m_syncRoot = new object();
      this.m_initHResult = 0;
      this.InsertThisRequestIntoDictionary();
    }

    public Exception ProcessingException
    {
      get
      {
        return this.m_processingException;
      }
      set
      {
        this.m_processingException = value;
      }
    }

    public IWebProxy UserProxy
    {
      get
      {
        if (this.m_proxy == null)
          this.m_proxy = WebRequest.GetSystemWebProxy();
        return this.m_proxy;
      }
    }

    public int UserLanguage
    {
      get
      {
        InfoCardTrace.Assert(this.m_lcid >= 0, " The user language has not been set in the service");
        return this.m_lcid;
      }
      set
      {
        this.m_lcid = value;
      }
    }

    protected Stream InArgs
    {
      get
      {
        return this.m_inArgs;
      }
    }

    public Stream OutArgs
    {
      get
      {
        return this.m_outArgs;
      }
    }

    protected object SyncRoot
    {
      get
      {
        return this.m_syncRoot;
      }
    }

    protected IntPtr RpcHandle
    {
      get
      {
        return this.m_rpcHandle;
      }
    }

    public int RequestHandle
    {
      get
      {
        return this.m_requestHandle;
      }
    }

    public abstract WindowsIdentity RequestorIdentity { get; }

    internal void Initialize()
    {
      try
      {
        this.OnInitializeAsSystem();
        this.ImpersonateRequestor();
        this.OnInitializeAsUser();
      }
      catch (Exception ex)
      {
        this.m_initHResult = this.HandleException(ex, true);
      }
    }

    private void ImpersonateRequestor()
    {
      InfoCardTrace.Assert(null != this.RequestorIdentity, "RequestorIdentity can not be null, the derived class  should have populated this on initialize");
      if (this.RequestorIdentity.IsSystem)
        throw InfoCardTrace.ThrowHelperError((Exception) new CommunicationException(SR.GetString("UserIdentityEqualSystemNotSupported")));
      this.m_impersonationContext = this.RequestorIdentity.Impersonate();
    }

    private int GetHResultFromException(Exception e)
    {
      int num = 0;
      Type type = e.GetType();
      if (Request.s_exceptionToHResultTable.ContainsKey(type))
        num = Request.s_exceptionToHResultTable[type];
      else if (e is Win32Exception)
        num = ((Win32Exception) e).NativeErrorCode;
      else
        InfoCardService.Crash(e);
      return num;
    }

    protected int HandleException(Exception e)
    {
      return this.HandleException(e, false);
    }

    protected int HandleException(Exception e, bool isInitializing)
    {
      int errorCode = 0;
      if (InfoCardTrace.IsFatal(e))
      {
        InfoCardTrace.TraceAndLogException(e);
        InfoCardService.Crash(e);
      }
      Exception exception = !(e is InfoCardRequestException) ? e : e.InnerException;
      if (isInitializing || !this.OnHandleException(exception, out errorCode))
      {
        if (exception is InfoCardBaseException)
        {
          errorCode = ((InfoCardBaseException) exception).NativeHResult;
          this.m_extendedErrorMessage = ((InfoCardBaseException) exception).ExtendedMessage;
        }
        else if (this.m_recoverableExceptions == ExceptionList.AllNonFatal)
        {
          CommunicationException communicationException = new CommunicationException(SR.GetString("ClientAPIInfocardError"), exception);
          InfoCardTrace.TraceAndLogException((Exception) communicationException);
          errorCode = communicationException.NativeHResult;
        }
        else if (this.m_recoverableExceptions.Contains(exception.GetType()))
        {
          errorCode = this.GetHResultFromException(exception);
        }
        else
        {
          InfoCardTrace.TraceAndLogException(e);
          InfoCardService.Crash(e);
        }
      }
      return errorCode;
    }

    protected virtual void PreProcessRequest()
    {
      this.ProcessingException = (Exception) null;
      this.OnMarshalInArgs();
      if (this.ProcessingException != null)
      {
        Exception processingException = this.ProcessingException;
        this.ProcessingException = (Exception) null;
        throw InfoCardTrace.ThrowHelperError((Exception) new InfoCardRequestException(processingException.Message, processingException));
      }
      if (this.InArgs.Position != this.InArgs.Length)
        throw InfoCardTrace.ThrowHelperError((Exception) new CommunicationException(SR.GetString("ServiceInvalidDataInRequest")));
      this.InArgs.Close();
    }

    protected virtual void PostProcessRequest()
    {
      this.ProcessingException = (Exception) null;
      this.OutArgs.Flush();
      this.OnMarshalOutArgs();
      if (this.ProcessingException != null)
      {
        Exception processingException = this.ProcessingException;
        this.ProcessingException = (Exception) null;
        throw InfoCardTrace.ThrowHelperError((Exception) new InfoCardRequestException(processingException.Message, processingException));
      }
    }

    protected virtual void ProcessRequest()
    {
      this.ProcessingException = (Exception) null;
      this.OnProcess();
      if (this.ProcessingException != null)
      {
        Exception processingException = this.ProcessingException;
        this.ProcessingException = (Exception) null;
        throw InfoCardTrace.ThrowHelperError((Exception) new InfoCardRequestException(processingException.Message, processingException));
      }
    }

    public int DoProcessRequest(out string extendedMessage)
    {
      int num = this.m_initHResult;
      if (num == 0)
      {
        try
        {
          this.PreProcessRequest();
          this.ProcessRequest();
          this.PostProcessRequest();
        }
        catch (Exception ex)
        {
          num = this.HandleException(ex);
        }
      }
      extendedMessage = this.m_extendedErrorMessage;
      return num;
    }

    public static Request FindRequestByHandle(int requestHandle)
    {
      lock (Request.s_syncRoot)
        return Request.s_existingClientRequests[requestHandle];
    }

    public void Dispose()
    {
      this.OnDisposeAsUser();
      if (this.m_impersonationContext != null)
      {
        this.m_impersonationContext.Undo();
        this.m_impersonationContext = (WindowsImpersonationContext) null;
      }
      this.OnDisposeAsSystem();
      this.RemoveThisRequestFromDictionary();
      GC.SuppressFinalize((object) this);
    }

    protected virtual void OnInitializeAsSystem()
    {
    }

    protected virtual void OnInitializeAsUser()
    {
    }

    protected virtual void OnDisposeAsUser()
    {
    }

    protected abstract void OnMarshalInArgs();

    protected abstract void OnProcess();

    protected abstract void OnMarshalOutArgs();

    protected virtual void OnDisposeAsSystem()
    {
    }

    protected virtual bool OnHandleException(Exception e, out int errorCode)
    {
      errorCode = 0;
      return false;
    }

    private void InsertThisRequestIntoDictionary()
    {
      lock (Request.s_syncRoot)
      {
        int newHandle;
        try
        {
          newHandle = Request.s_existingClientRequests.GetNewHandle();
        }
        catch (IndexOutOfRangeException ex)
        {
          throw InfoCardTrace.ThrowHelperError((Exception) new ServiceBusyException(SR.GetString("TooManyClientRequests"), (Exception) ex));
        }
        this.m_requestHandle = newHandle;
        Request.s_existingClientRequests[this.m_requestHandle] = this;
      }
    }

    private void RemoveThisRequestFromDictionary()
    {
      lock (Request.s_syncRoot)
        Request.s_existingClientRequests.Remove(this.m_requestHandle);
    }

    private class RequestHandleDictionary : HandleDictionary<Request>
    {
    }
  }
}
